package cn.chi.user.service.impl;

import cn.chi.base.constant.WxConstants;
import cn.chi.user.domain.LoginInfo;
import cn.chi.user.domain.User;
import cn.chi.user.domain.WxUser;
import cn.chi.user.mapper.LoginInfoMapper;
import cn.chi.user.mapper.UserMapper;
import cn.chi.user.mapper.WxUserMapper;
import cn.chi.user.service.IWxUserService;
import cn.chi.util.AjaxResult;
import cn.chi.util.HttpClientUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
public class WxUserServiceImpl implements IWxUserService {
    @Autowired
    private WxUserMapper wxUserMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private LoginInfoMapper loginInfoMapper;

    @Autowired
    private RedisTemplate redisTemplate;
    @Override
    public AjaxResult wxLogin(Map<String, String> map) {
        //1.通过code获取access_token  代码发送请求
        String url = WxConstants.GET_ACK_URL
                .replace("APPID",WxConstants.APPID)
                .replace("SECRET",WxConstants.SECRET)
                .replace("CODE",map.get("code"));
        //申请access_token 返回值
        String ackResult = HttpClientUtils.httpGet(url);
        System.out.println(ackResult);
        //2.获取里面的openid [使用工具 fastjson]
        JSONObject jsonObject = JSON.parseObject(ackResult);
        String openid = jsonObject.getString("openid");
        String access_token = jsonObject.getString("access_token");
        //3.根据openid 查询数据库
        WxUser wxUser = wxUserMapper.loadByOpenId(openid);
        //4.如果是老用户 t_wxuser  -->t_user-->对应的loginInfo
        if (wxUser!=null){
            // 对象不为空是老用户直接免密登录
            User user = userMapper.queryById(wxUser.getUser_id());
            //获取当前的微信用户 对应的 登录信息
            LoginInfo loginInfo = loginInfoMapper.queryById(user.getLogininfo_id());
            return  noPwdLogin(loginInfo);
        } else {
            // 没有查询到用户数据:新用户条转到注册页面
            return AjaxResult.me().setMessage("bind").setResultObj("/binder.html?openid="+openid+"&access_token="+access_token);
        }
    }


    /**
     * 新用户验证码绑定数据入库
     * @param map
     * @return
     */
    @Override
    public AjaxResult bind(Map<String, String> map) {
        // 获取数据 [phone ,code ,openid ,access_token ]用于验证数据

        String phone = map.get("phone");
        String code = map.get("code");
        String openid = map.get("openid");
        String access_token = map.get("access_token");
        // 1验证验证码是否准确
        String codeInRedis  = (String) redisTemplate.opsForValue().get(phone + ":BINDER");
        if (codeInRedis!=null){
            codeInRedis=codeInRedis.split(":")[0];
            if(!codeInRedis.equals(code)){
                return  new AjaxResult("验证码错误，请重新发送");
            }
        }else {
            return  new AjaxResult("验证码过期，请重新发送");
        }
        //拼接请求地址
        String url = WxConstants.GET_USERINFO_URL
                .replace("ACCESS_TOKEN",access_token)
                .replace("OPENID",openid);
        // 发送请求获取用户数据
        String infoResult  = HttpClientUtils.httpGet(url);
        // 打印用户数据测试是否拿到了
        System.out.println(infoResult);
        //把微信用户的个人信息 解析
        JSONObject jsonObject = JSON.parseObject(infoResult);
        // 封装解析到的用户数据用于存进数据库
        WxUser wxUser = new WxUser();
        wxUser.setOpenid(openid);
        wxUser.setNickname(jsonObject.getString("nickname"));
        wxUser.setSex(jsonObject.getInteger("sex"));
        wxUser.setHeadimgurl(jsonObject.getString("headimgurl"));
        wxUser.setUnionid(jsonObject.getString("unionid"));
        // 通过phone查询该用户是否已经注册了
        User user = userMapper.queryById(wxUser.getUser_id());
        LoginInfo loginInfo=null;
        // 业务逻辑判断
        if(user==null){
            // 用户为空,生成用户信息存进数据库
            user=new User();
            user.setPhone(phone);
            user.setUsername("p_"+phone);
            user.setState(1);
            user.setCreatetime(new Date());
            // 数据转换存进logininfo表中
            loginInfo =user2LoginInfo(user);
            // 存入数据库 保存loginInfo 返回新增数据的主键
            loginInfoMapper.save(loginInfo);
            //获取主键绑定
            user.setLogininfo_id(loginInfo.getId());
            // 入库
            userMapper.save(user);
        }
        //获取用户的id进行绑定
        wxUser.setUser_id(user.getId());
        wxUserMapper.save(wxUser);
        // 补全业务逻辑:保证logininfo中有数据
        if (user!=null){
            loginInfo = loginInfoMapper.queryById(user.getLogininfo_id());
        }
        //免密登录
        return noPwdLogin(loginInfo);
    }

    /**
     * 数据转换
     * @param user
     * @return
     */
    private LoginInfo user2LoginInfo(User user) {
        LoginInfo loginInfo = new LoginInfo();
        BeanUtils.copyProperties(user,loginInfo);
        loginInfo.setType(1);
        loginInfo.setDisable(1);
        return loginInfo;
    }

    /**
     * 免密登录数据处理
     * @param loginInfo
     * @return
     */
    private AjaxResult noPwdLogin(LoginInfo loginInfo) {
        //生成token
        String token = UUID.randomUUID().toString();
        //把当前用户和token 放到redis里面  并设置有效期是30分钟
        redisTemplate.opsForValue().set(token,loginInfo,30, TimeUnit.MINUTES);
        //把 token  登录用户 返回给前端
        Map<String,Object> map = new HashMap();
        map.put("TOKEN",token);
        //返回给前端以前 清空敏感数据
        loginInfo.setPassword(null);
        loginInfo.setSalt(null);

        map.put("loginInfo",loginInfo);
        return AjaxResult.me().setResultObj(map);
    }
}
